package com.bankcoder.operation;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.Sheet;
import com.bankcoder.QualityManagementApplication;
import com.bankcoder.entity.*;
import com.bankcoder.listener.CheckHostReviewListener;
import com.bankcoder.listener.UnitTestListener;

import javax.sound.midi.Soundbank;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;



public class DoCheckRule {
    //因为文件名有特殊字符，所以先将程序放在当前检查的当前目录
    File file=new File(QualityManagementApplication.getAllFilesPath());
    //public static final String checkPath="G:\\cmpDemo";

    //File file=new File(checkPath);


    /**
     * 检查文件名规则
     * @param cmpCheckEntity
     * @return
     */
    public List<ResultModel> checkFileName(CmpCheckEntity cmpCheckEntity){
        //根据程序processName-tranName进行唯一索引   使用+连接，避免空指针异常
        String index = cmpCheckEntity.getProcessName().concat("-")+cmpCheckEntity.getTranName();
        //需要记录那一层文件夹{主机导图,详细设计等等}问题与问题描述，由于是递归调用，所以全局变量不能放在方法中创建
        Map<String,String> probMap =new HashMap<String, String>();
        int checkItemZjslNum=0;
        int checkItemJkyhNum=0;
        int checkItemXxsjNum=0;
        int checkItemPsjlNum=0;
        int checkItemDycsNum=0;
        int checkItemDmsmNum=0;
        //根据文件名一部分，递归查询整个目录
        probMap=findFile(file,index,checkItemZjslNum,checkItemJkyhNum,checkItemXxsjNum,checkItemPsjlNum,checkItemDycsNum,checkItemDmsmNum,probMap);
        //检查完之后应该写文件了
        List<ResultModel> list=new ArrayList<ResultModel>();
        //由于一个程序名-交易名的probMap可能包含多个值，所以要对其进行遍历
        for(String key:probMap.keySet()){//keySet获取map集合key的集合  然后在遍历key即可
            String value = probMap.get(key).toString();
            //System.out.println("key:"+key+"-value:"+value);
            //已经检查到的记录这里整理，准备往目标文件登记
            //第一步：准备目标文件模板对应的实体类 {CheckResultEntity}
            //第二步：组织写入excel文件内容
            ResultModel resultModel = this.assembleResultModel(cmpCheckEntity,key,value);
            //System.out.println(resultModel.toString());
            list.add(resultModel);
        }
        //System.out.println("List集合大小"+list.size()+"====list中数据"+list.toString());

        return list;
    }

    /**
     * 递归检索文件名
     * @param file
     * @param index
     * @param checkItemZjslNum
     * @param checkItemJkyhNum
     * @param checkItemXxsjNum
     * @param checkItemPsjlNum
     * @param checkItemDycsNum
     * @param checkItemDmsmNum
     * @return
     */
    private Map<String,String> findFile(File file, String index,
                                        int checkItemZjslNum,
                                        int checkItemJkyhNum,
                                        int checkItemXxsjNum,
                                        int checkItemPsjlNum,
                                        int checkItemDycsNum,
                                        int checkItemDmsmNum,
                                        Map<String,String> map){
        File[] fs = file.listFiles();
        for(File f:fs){
            if(f.isDirectory()){
                //若是目录，则递归打印该目录下的文件
                findFile(f,index,checkItemZjslNum,checkItemJkyhNum,checkItemXxsjNum,checkItemPsjlNum,checkItemDycsNum,checkItemDmsmNum,map);
            }
            if(f.isFile()){
                //找到文件了，匹配文件名
                if(f.getName().contains(index)){
                    //System.out.println("文件路径==>"+f.getAbsolutePath()+";文件名==>"+f.getName());
                }else{//没有找到文件，说明要么是没有上传文件，要么是文件命名不规范
                    //如果当前路径未找到文件，则按不同文件夹描述错误信息
                    //例如，如果在主机梳理中没有找到，则会记录“此程序未提交思维导图，请注意”
                    if(f.getAbsolutePath().contains(CheckItem.checkItemZjsl.item)){
                        checkItemZjslNum+=1;
                    }
                    if(f.getAbsolutePath().contains(CheckItem.checkItemJkyh.item)){
                        checkItemJkyhNum+=1;
                    }
                    if(f.getAbsolutePath().contains(CheckItem.checkItemXxsj.item)){
                        checkItemXxsjNum+=1;
                    }
                    if(f.getAbsolutePath().contains(CheckItem.checkItemPsjl.item)){
                        checkItemPsjlNum+=1;
                    }
                    if(f.getAbsolutePath().contains(CheckItem.checkItemDycs.item)){
                        checkItemDycsNum+=1;
                    }
                    if(f.getAbsolutePath().contains(CheckItem.checkItemDmsm.item)){
                        checkItemDmsmNum+=1;
                    }

                }

            }
        }
        //todo 问题可能要登记到这里
        //都循环完了，根据统计的次数进行输出
        if(checkItemZjslNum>0){
            map.put(CheckItem.checkItemZjsl.item,"未找到:思维导图");
        }
        if(checkItemJkyhNum>0){
            map.put(CheckItem.checkItemJkyh.item,"未找到:接口文档");
        }
        if(checkItemXxsjNum>0){
            map.put(CheckItem.checkItemXxsj.item,"未找到:详细设计");
        }
        if(checkItemPsjlNum>0){
            map.put(CheckItem.checkItemPsjl.item,"未找到:评审记录");
        }
        if(checkItemDycsNum>0){
            map.put(CheckItem.checkItemDycs.item,"未找到:单元测试");
        }
        if(checkItemDmsmNum>0){
            map.put(CheckItem.checkItemDmsm.item,"未找到:代码扫描");
        }
        return map;
    }


    public ResultModel assembleResultModel(CmpCheckEntity cmpCheckEntity,String key,String value){
        ResultModel result=new ResultModel();
        result.setId("");
        result.setGroupName(cmpCheckEntity.getBusinessUnit());
        result.setPhase("其他");//先写其他，后面根据场景进行判断
        result.setProcessCode(cmpCheckEntity.getProcessName());
        result.setTranDesc(cmpCheckEntity.getTranName());
        result.setCheckFile(key);//
        result.setProblemDesc(value);
        result.setProblemType("工作产品");//暂时无法匹配到
        result.setResponser(cmpCheckEntity.getDeveloper());
        result.setCheckDate(getDate(0));
        result.setStatus("新建");//所有问题初始状态都是新建
        result.setIsAccepted("");
        result.setRefuseReason("");
        result.setPlanDate(getDate(5));
        result.setSolution("");
        result.setSolutionDate("");
        result.setUseTime("");
        return result;
    }

    /**
     * 格式化当前自然日期
     * @return 当前自然日期
     */
    public String getDate(Integer addDays){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date currentDate=new Date();
        return sdf.format(new Date(currentDate.getTime() + addDays * 24 * 60 * 60 * 1000));
    }

    //检查主机梳理评审记录

    /**
     *
     * @param cmpCheckEntity
     * @return 对于每一个程序-程序名的组合，检查评审记录中不通过的或不存在的
     */
    public List<ResultModel> checkHostReview(CmpCheckEntity cmpCheckEntity){
        List<ResultModel> list=new ArrayList<ResultModel>();
        //根据程序processName-tranName进行唯一索引,到所有评审记录中找文件
        String index = cmpCheckEntity.getProcessName().concat("-")+cmpCheckEntity.getTranName();
        //map -->  {主机梳理：未找到主机梳理评审记录或评审状态不通过}
        Map<String,String> map=new HashMap<String, String>();
        //map.put("主机梳理","未找到主机梳理评审记录或评审状态不通过");
        //递归查找文件夹中包含”评审记录“，然后按上面索引找到文件,并获取文件内容格式如下：
        /**
         * CheckHostReview{, number='1', topic='评审程序设计导图', conclusion='不通过'}
         * CheckHostReview{, number='2', topic='评审详细设计', conclusion='不通过'}
         * CheckHostReview{, number='4', topic='接口文档', conclusion='不通过'}
         */
        map=findFile(file,index,map);
        //依次循环不通过的检查项并登记
        for(String key:map.keySet()){
            String value = map.get(key);
            //组织模型
            ResultModel resultModel=this.assembleResultModel(cmpCheckEntity,key,value);
            list.add(resultModel);
        }
        return list;
    }



    private Map<String,String> findFile(File file, String index, Map<String,String> probMap){
        File[] fs = file.listFiles();
        for(File f:fs) {
            if (f.isDirectory()) {
                //若是目录，则递归打印该目录下的文件
                findFile(f, index, probMap);
            }
            if (f.isFile()) {
                //找到文件了，匹配文件名
                if (f.getName().contains(index) && f.getAbsolutePath().contains("评审记录")) {
                    //System.out.println("文件路径==>" + f.getAbsolutePath() + ";文件名==>" + f.getName());
                    //打开文件，然后读取文件内容
                    CheckHostReviewListener hostReviewListener=new CheckHostReviewListener<CheckHostReview>();
                    EasyExcel.read(f.getAbsolutePath(), CheckHostReview.class,hostReviewListener).sheet("评审记录").doRead();
                    List<CheckHostReview> hostReviews = hostReviewListener.getHostReviews();
                    //获取到主机梳理所在的行
                    for(CheckHostReview checkHostReview: hostReviews){
                        if(checkHostReview.getTopic()!=null && !checkHostReview.getTopic().trim().isEmpty()){
                            if(checkHostReview.getTopic().contains("导图")&&"不通过".equals(checkHostReview.getConclusion().trim())){
                                //System.out.println("yangmlb==="+checkHostReview.toString());
                                probMap.put("导图评审","导图评审:不通过");
                            }
                            if((checkHostReview.getTopic().contains("详细设计")|| checkHostReview.getTopic().contains("详设"))&&"不通过".equals(checkHostReview.getConclusion().trim())){
                                //System.out.println("yangmlb==="+checkHostReview.toString());
                                probMap.put("详细设计","详细设计评审:不通过");
                            }
                            if(checkHostReview.getTopic().contains("代码")&&"不通过".equals(checkHostReview.getConclusion().trim())){
                                //System.out.println("yangmlb==="+checkHostReview.toString());
                                probMap.put("代码评审","代码评审:不通过");
                            }
                            if(checkHostReview.getTopic().contains("接口")&&"不通过".equals(checkHostReview.getConclusion().trim())){
                                //System.out.println("yangmlb==="+checkHostReview.toString());
                                probMap.put("接口文档","接口文档评审:不通过");
                            }
                        }

                    }
                }
            }
        }
        return probMap;
    }

    public List<ResultModel> checkUintTestResult(CmpCheckEntity cmpCheckEntity){
        List<ResultModel> list=new ArrayList<ResultModel>();
        //根据程序processName-tranName进行唯一索引,到所有评审记录中找文件
        String index = cmpCheckEntity.getProcessName().concat("-")+cmpCheckEntity.getTranName();
        //map -->  {}
        Map<String,String> map=new HashMap<String, String>();
        //为了避免递归调用导致数据丢失，所以由外向内传数据
        this.findFileForTest(file,index,map);
        //依次循环不通过的检查项并登记
        for(String key:map.keySet()){
            String value = map.get(key);
            //组织模型
            ResultModel resultModel=this.assembleResultModel(cmpCheckEntity,key,value);
            list.add(resultModel);
        }

        return list;
    }

    /**
     * 查询单元文件，返回问题描述
     * @param file
     * @param index
     * @param probMap
     * @return
     */
    private void findFileForTest(File file, String index, Map<String,String> probMap){
        File[] fs = file.listFiles();
        for(File f:fs) {
            if (f.isDirectory()) {
                //若是目录，则递归打印该目录下的文件
                findFileForTest(f, index, probMap);
            }
            if (f.isFile()) {
                //找到文件了，匹配文件名     //todo 后面对比全路径名可能会导致问题出现，应该对比文件夹名
                if (f.getName().contains(index) && f.getPath().contains("单元测试")) {
                    //System.out.println("文件路径==>" + f.getPath() + ";文件名==>" + f.getName());
                    //打开文件，然后读取文件内容
                    UnitTestListener unitTestListener=new UnitTestListener<UnitTestEntity>();
                    EasyExcel.read(f.getAbsolutePath(), UnitTestEntity.class,unitTestListener).sheet("案例列表").doRead();
                    List<UnitTestEntity> unitTests = unitTestListener.getList();
                    //获取到主机梳理所在的行
                    if(unitTests !=null && unitTests.size()>0){
                        //检查测试案例数量够不够
                        int count=0;
                        if(unitTests.size()<8){
                            probMap.put("单元测试数量","测试案例数量小于4条，请确认");
                        }
                        //根据acv查询ACV对应的sheet页是否存在
                        com.alibaba.excel.ExcelReader excelReader = EasyExcel.read(f.getAbsoluteFile()).build();
                        List<Sheet> sheets=excelReader.getSheets();
                        List<String> sheetNames=new ArrayList<String>();
                        if(null !=sheets&& sheets.size()>0){
                            for(Sheet sheet:sheets){
                                sheetNames.add(sheet.getSheetName());
                            }
                        }
                        for(UnitTestEntity unitTestEntity:unitTests){

                            System.out.println("yangmlb=====>"+unitTestEntity.toString());
                            //检查有没有未通过的测试案例
                            if("不通过".equals(unitTestEntity.getStatus())){
                                probMap.put("单元测试状态","此条案例不通过:"+unitTestEntity.getACV());
                            }
                            if(!"".equals(unitTestEntity.getACV())&& null!=unitTestEntity.getACV()&& unitTestEntity.getACV().contains("_")){
                                count+=1;
                                if(null!=sheetNames&&sheetNames.size()>0){
                                    if(!sheetNames.contains(unitTestEntity.getACV())){
                                        probMap.put("单元测试报文","单元测试案例"+unitTestEntity.getACV()+"不包含对应报文sheet页");
                                    }
                                }
                            }
                        }
                        if(count<4){
                            probMap.put("单元测试数量","测试案例数量小于4条，请确认");
                        }
                    }
                }
            }
        }

    }




}



